package org.dfl.plugin.views.actions;

import java.util.Set;

import org.dfl.core.data.types.CollectionType;
import org.dfl.core.data.types.Type;
import org.dfl.plugin.DflPlugin;
import org.dfl.plugin.dialogs.DialogsManager;
import org.dfl.plugin.views.ViewsManager;
import org.dfl.plugin.views.debug.model.CollectionTreeElem;
import org.dfl.plugin.views.debug.model.DataTreeElem;
import org.dfl.plugin.views.debug.model.HistoryColTreeElem;
import org.dfl.plugin.views.debug.model.HistoryTreeElem;
import org.dfl.plugin.views.debug.model.MapKeyTreeElem;
import org.dfl.plugin.views.debug.model.MapTreeElem;
import org.dfl.plugin.views.debug.model.TokenTreeElem;
import org.dfl.plugin.views.debug.model.TreeElem;
import org.dfl.plugin.views.debug.model.TreeElemImpl;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.actions.ActionDelegate;

/**
 * action that provide pasting objects. It's used in
 * a HistoriesTreeView and TokensTreeView (see mapping in plugin.xml file)
 * 
 * @author Piotr Wlodarczyk
 * 
 */
public class PasteContentAction extends ActionDelegate {

	private IStructuredSelection selection = StructuredSelection.EMPTY;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.actions.ActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
	 *      org.eclipse.jface.viewers.ISelection)
	 */
	public void selectionChanged(IAction action, ISelection sel) {
		if (sel instanceof IStructuredSelection)
			selection = (IStructuredSelection) sel;
		else
			selection = StructuredSelection.EMPTY;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.actions.ActionDelegate#run(org.eclipse.jface.action.IAction)
	 */
	public void run(IAction action) {
		if (selection.isEmpty())
			return;
		Object parent = selection.getFirstElement();
		Set<TreeElem> toPasteElems = CopyContentAction.getCopyElems();
		if (toPasteElems.isEmpty()) {
			return;
		}
		for (TreeElem toPasteElem : toPasteElems) {
			if(!(toPasteElem instanceof DataTreeElem)){
				continue;
			}
			DataTreeElem toPaste = (DataTreeElem) toPasteElem;
			if (parent instanceof MapKeyTreeElem) {
				TreeElem child = ((MapKeyTreeElem) parent).getChild();
				if (child == null) {
					MapKeyTreeElem parentElem = (MapKeyTreeElem) parent;
					Type t = parentElem.getType();
					if (!toPaste.getType().canMerge(t)) {
						DialogsManager
								.openErrorDialog("An element has a wrong type and cannot be pasted here!");
						return;
					}
					synchronized (DflPlugin.class) {
						parentElem.addChild(toPaste.getCopy());
						parentElem.update();
						ViewsManager.refreshViews(parentElem);
					}
				} else {
					parent = ((MapKeyTreeElem) parent).getChild();
				}
			}

			if (parent instanceof TokenTreeElem) {
				TokenTreeElem tokenElem = (TokenTreeElem) parent;
				Type t = ((TokenTreeElem) parent).getType();
				if (!toPaste.getType().canMerge(t)) {
					DialogsManager
							.openErrorDialog("The element has a wrong type and cannot be pasted here!");
					return;
				}
				TreeElem newElem = toPaste.getCopy();
				if (newElem != null) {
					synchronized (DflPlugin.class) {
						tokenElem.setNewChild((TreeElemImpl) newElem);
						tokenElem.update();
					}
					ViewsManager.refreshViews(tokenElem);
				}
			} else if (parent instanceof HistoryTreeElem) {
				if (!(toPaste instanceof HistoryColTreeElem)) {
					DialogsManager
							.openErrorDialog("You can paste here only history collections!");
					return;
				}
				HistoryTreeElem historyElem = (HistoryTreeElem) parent;
				synchronized (DflPlugin.class) {
					historyElem.addFirstChild(
							(HistoryColTreeElem) ((HistoryColTreeElem) toPaste)
									.getCopyFullCopy());
					historyElem.update();
				}
				ViewsManager.refreshViews(historyElem);
			} else if (parent instanceof CollectionTreeElem) {
				CollectionTreeElem elem = (CollectionTreeElem) parent;
				CollectionType t = (CollectionType) ((DataTreeElem) parent)
						.getType();
				if (!toPaste.getType().canMerge(
						t.getSubtypeContainer().getType())) {
					DialogsManager
							.openErrorDialog("The element has a wrong type and cannot be pasted here!");
					return;
				}
				synchronized (DflPlugin.class) {
					elem.addChild(toPaste.getCopy());
					elem.update();
				}
				ViewsManager.refreshViews(elem);
			} else if (parent instanceof MapTreeElem) {
				if (!(toPaste instanceof MapKeyTreeElem)) {
					DialogsManager
							.openErrorDialog("You can paste here only map elements!");
					return;
				}
				MapTreeElem elem = (MapTreeElem) parent;
				synchronized (DflPlugin.class) {
					elem.addChild(toPaste.getCopy());
					elem.update();
				}
				ViewsManager.refreshViews(elem);
			}
		}
	}
}
